package com.ncmmall.api.apis.mall;


import com.ncmmall.api.apis.service.Result;
import com.ncmmall.api.params.WebUserDTO;
import com.ncmmall.api.security.Securitys;
import com.ncmmall.api.utils.WXBizDataCrypt;
import com.ncmmall.application.business.live.LiveApplication;
import com.ncmmall.application.business.member.MemberApplication;
import com.ncmmall.application.util.WechatMessageUtils;
import com.ncmmall.cache.redis.RedisService;
import com.feijin.commons.lang.PropertiesHelps;
import com.feijin.commons.securitys.MD5HashUtils;
import com.ncmmall.domain.business.setting.SystemSetting;
import com.ncmmall.domain.security.user.QWebUser;
import com.ncmmall.domain.security.user.WebUser;
import com.ncmmall.querychannel.service.QueryChannelService;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;
import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.Collections;

/**
 * @author linxs
 * 用户注册、登录、退出接口
 */
@RestController
@RequestMapping(value = "/security")
@Slf4j
public class UserApi {

    @Autowired
    private QueryChannelService queryChannelService;

    @Autowired
    private MemberApplication memberApplication;

    @Autowired
    private RedisService redisService;

    private static final String STORE_DOMAIN = PropertiesHelps.getValue("store.domain");

    /**
     * 登录
     */
    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public Result login(HttpServletRequest request, @RequestBody WebUser params) {

        Result result = new Result();
        try {

            WebUser user = queryChannelService.findOne("select u from WebUser u where u.username = :username and u.role.name = 'MEMBER' ", ImmutableMap.of("username", params.getUsername()), WebUser.class);

            if (user != null) {

                String passwordAsMd5 = MD5HashUtils.asMD5(params.getPassword(), params.getUsername());

                if (user.getPassword().equals(passwordAsMd5)) {
                    user = memberApplication.login(user, Securitys.ipAddress(request));
                    log.info("[登录会员]" + user.getId() + "  " + user.getRealName() + "   " + user.getUsername() + "   " + user.getAccessToken() + "   " + user.getRefreshToken() + "    " + user.getMobile());
                    return result.ok().inject(ImmutableMap.of("token", user.getAccessToken(), "refreshToken", user.getRefreshToken(), "bindMobileStatus", !Strings.isNullOrEmpty(user.getMobile())));
                }

                return result.fail().setMsg("账号密码错误");
            }


            return result.fail().setMsg("账号不存在");

        } catch (Exception e) {
            log.error("[登录异常]", e);
            return result.fail().setMsg("登录异常");
        }

    }

    /**
     * token过期后，24小时内可以获取新的token
     */
    @RequestMapping(value = "/refreshToken", method = RequestMethod.POST)
    public Result refreshToken(HttpServletRequest request, @RequestBody WebUser params) {
        Result result = new Result();
        try {

            WebUser user = queryChannelService.queryOneEntity("select u.* from security_web_user u where u.refreshToken = :token and u.lastLoginTime > DATE_ADD(NOW(), INTERVAL -1440 MINUTE)", ImmutableMap.of("token", params.getRefreshToken()), WebUser.class);

            if (user != null) {
                memberApplication.login(user, Securitys.ipAddress(request));
                return result.ok().inject(ImmutableMap.of("token", user.getAccessToken(), "refreshToken", user.getRefreshToken()));
            }

            return result.fail().setMsg("登录信息已过期");

        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return result.fail().setMsg("登录异常");
        }

    }

    /**
     * 微信小程序授权获取手机号快捷登录
     */
    @RequestMapping(value = "/wechatRegister", method = RequestMethod.POST)
    public Result wechatRegister(HttpServletRequest request, @RequestBody WebUserDTO params) {

        Result result = new Result();
        try {

            WXBizDataCrypt pc = new WXBizDataCrypt(params.getSessionKey());
            JSONObject wechatData = pc.decryptData(params.getEncryptedData(), params.getIv());

            WebUser user = memberApplication.wechatLogin(wechatData.getString("purePhoneNumber"), params.getOpenid(), Securitys.ipAddress(request));
            return result.ok().inject(ImmutableMap.of("token", user.getAccessToken(), "refreshToken", user.getRefreshToken(), "isRegister", true));

//            //微信绑定的手机号码
//            String username = wechatData.getString("purePhoneNumber");
//
//            WebUser user = queryChannelService.findOne("select u from WebUser u where u.username = :username and (u.role.name = 'MEMBER' or u.role.name = 'ANCHOR') ", ImmutableMap.of("username", username), WebUser.class);
//
//            if (null != user) {
//                user = memberApplication.login(user, Securitys.ipAddress(request));
//                return result.ok().inject(ImmutableMap.of("token", user.getAccessToken(), "refreshToken", user.getRefreshToken(), "isRegister", false));
//            }
//
//            user = new WebUser();
//            user.setUsername(username);
//            user.setPassword(MD5HashUtils.asMD5("123456", username));
//            user.setMobile(username);
//            user.setOpenId(params.getOpenid());
//
//            memberApplication.register(user);
//
//            user = memberApplication.login(user, Securitys.ipAddress(request));
//            return result.ok().inject(ImmutableMap.of("token", user.getAccessToken(), "refreshToken", user.getRefreshToken(), "isRegister", true));

        } catch (IllegalArgumentException e) {
            return result.fail().setMsg(e.getMessage());
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return result.fail().setMsg("注册异常");
        }

    }

    /**
     * 注册成功后推送订阅消息
     */
    @RequestMapping(value = "/sentNotification", method = RequestMethod.POST)
    public Result sentNotification(HttpServletRequest request) {
        Result result = new Result();
        try {

            WebUser user = Securitys.user(request);

            JSONObject item = new JSONObject();
            item.put("time1", JSONObject.fromObject(ImmutableMap.of("value", new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss").format(user.getCreateTime()))));
            item.put("character_string2", JSONObject.fromObject(ImmutableMap.of("value", user.getUserNo())));

            WechatMessageUtils.send(user.getOpenId(), "Ssomj3hw3MAVikdg4i79bDQNU70V91Tr8Am2a_ENcNY", item.toString());

            return result.ok();

        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return result.fail().setMsg("注册异常");
        }

    }


    /**
     * 注册
     */
    @RequestMapping(value = "/register", method = RequestMethod.POST)
    public Result register(HttpServletRequest request, @RequestBody WebUserDTO params) {

        Result result = new Result();
        try {

//            WebUser user = queryChannelService.findOne("select u from WebUser u where u.username = :username", ImmutableMap.of("username", params.getUsername()), WebUser.class);
            long count = queryChannelService.selectCount("select count(*) from security_web_user where username = :username", ImmutableMap.of("username", params.getUsername()));

            if (count > 0) {
                return result.fail().setMsg("账号已存在，请直接登录");
            }

            String code = redisService.get("msm-" + params.getUsername());
            if (!params.getMobileCode().equals(code)) {
                return result.fail().setMsg("短信验证码不正确");
            }

            WebUser user = new WebUser();
            user.setUsername(params.getUsername());
            user.setPassword(MD5HashUtils.asMD5(params.getPassword(), params.getUsername()));
            user.setMobile(user.getUsername());
            user.setOpenId(params.getOpenid());

            memberApplication.register(user);

            user = memberApplication.login(user, Securitys.ipAddress(request));
            return result.ok().inject(ImmutableMap.of("token", user.getAccessToken(), "refreshToken", user.getRefreshToken()));

        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return result.fail().setMsg("注册异常");
        }

    }

    /**
     * 获取用户信息
     */
    @RequestMapping(value = "/userInfo", method = RequestMethod.GET)
    @ResponseBody
    public Result userInfo(HttpServletRequest request) {

        Result result = new Result();
        try {
            WebUser member = Securitys.cleanUser(request);
            member.setMessageCount(member.getSystemMessageNumber() + member.getOrderMessageNumber() + member.getWithDrawMessageNumber());

            int nonPaymentOrders = queryChannelService.selectCount("select count(*) from mall_order where member_id = :mid and status = 1", ImmutableMap.of("mid", member.getId()));
            int unfilledOrders = queryChannelService.selectCount("select count(*) from mall_order where member_id = :mid and status = 2", ImmutableMap.of("mid", member.getId()));
            int nonReceiveOrders = queryChannelService.selectCount("select count(*) from mall_order where member_id = :mid and status = 3", ImmutableMap.of("mid", member.getId()));
            int nonCommentOrders = queryChannelService.selectCount("select count(*) from mall_order where member_id = :mid and status = 4", ImmutableMap.of("mid", member.getId()));
            int afterSaleOrders = queryChannelService.selectCount("select count(*) from mall_order where member_id = :mid and isAfterSale = 1", ImmutableMap.of("mid", member.getId()));

            member.setNonPaymentOrders(nonPaymentOrders);
            member.setUnfilledOrders(unfilledOrders);
            member.setNonReceiveOrders(nonReceiveOrders);
            member.setNonCommentOrders(nonCommentOrders);
            member.setAfterSaleOrders(afterSaleOrders);

            member.setDistributorFlag(member.getDistributor() != null);
            if (member.getDistributor() != null) {
                member.setDistributiorStatus(member.getDistributor().getAccountStatus());
            }

            if (LiveApplication.checkUserIsAnchor(member)) {
                if (StringUtils.isNotBlank(member.getLiveImage())) {
                    member.setLiveImage(STORE_DOMAIN + "/uploads/" + member.getLiveImage());
                }
                member.setFansNumber(queryChannelService.selectCount("select count(*) from live_fans where anchor_id = :uid",
                        ImmutableMap.of("uid", member.getId())));
            }

            if (member.getLiveType() == 2) {
                member.setAnchorId(member.getAnchor() != null ? member.getAnchor().getId() : null);
            }

            return result.ok().inject(member);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            result.fail().setMsg(e.getMessage());
        }

        return result;
    }


    /**
     * 更改昵称
     */
    @RequestMapping(value = "/modifyNickname", method = RequestMethod.PUT)
    public Result modifyNickname(HttpServletRequest request, @RequestBody WebUserDTO webUserDTO) {

        Result result = new Result();

        try {

            WebUser member = Securitys.user(request);
            memberApplication.modifyNickname(member, webUserDTO.getNickname());
            return result.ok();

        } catch (Exception e) {
            log.error("[修改昵称异常]", e);
            return result.fail().setMsg("修改失败");
        }

    }

    /**
     * 修改性别
     */
    @RequestMapping(value = "/sex", method = RequestMethod.PUT)
    public Result sex(HttpServletRequest request, @RequestBody WebUserDTO webUserDTO) {
        Result result = new Result();
        try {
            WebUser member = Securitys.user(request);
            memberApplication.modifySex(member, webUserDTO.getSex());
            return result.ok();
        } catch (Exception e) {
            log.error("[修改昵称异常]", e);
            return result.fail().setMsg("修改失败");
        }
    }


    /**
     * 更改个性签名
     */
    @RequestMapping(value = "/modifySignature", method = RequestMethod.PUT)
    public Result modifySignature(HttpServletRequest request, @RequestBody WebUserDTO params) {
        Result result = new Result();
        try {
            WebUser member = Securitys.user(request);
            memberApplication.modifySignature(member, params.getSignature());
            return result.ok();
        } catch (Exception e) {
            log.error("[修改个性签名异常]", e);
            return result.fail().setMsg("修改失败");
        }
    }


    /**
     * 更改头像
     */
    @RequestMapping(value = "/modifyAvatar", method = RequestMethod.PUT)
    public Result modifyAvatar(HttpServletRequest request, @RequestBody WebUserDTO params) {
        Result result = new Result();
        try {
            WebUser member = Securitys.user(request);
            memberApplication.modifyAvatar(member, params.getAvatar());
            return result.ok();
        } catch (Exception e) {
            log.error("[修改头像异常]", e);
            return result.fail().setMsg("修改失败");
        }
    }

    /**
     * 修改密码
     */
    @RequestMapping(value = "/modifyPassword", method = RequestMethod.PUT)
    public Result editPassword(HttpServletRequest request, @RequestBody WebUserDTO webUserDTO) {
        Result result = new Result();
        try {
            WebUser user = Securitys.user(request);
            if (StringUtils.isBlank(webUserDTO.getMobileCode()) || !webUserDTO.getMobileCode().equals(redisService.get("msm-" + user.getMobile()))) {
                return result.fail().setMsg("验证码不正确");
            }
            memberApplication.modifyPassword(user, webUserDTO.getNewPassword());
            return result.ok();
        } catch (Exception e) {
            log.error("[修改密码异常]", e);
            return result.fail().setMsg("修改失败");
        }
    }

    /**
     * 退出登录
     */
    @RequestMapping(value = "/logout", method = RequestMethod.POST)
    public Result logout(HttpServletRequest request) {
        Result result = new Result();
        try {
            memberApplication.logout(Securitys.token(request));
            return result.ok();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return result.fail().setMsg("退出失败");
        }
    }

    /**
     * 忘记密码
     */
    @RequestMapping(value = "/forgetPassword", method = RequestMethod.PUT)
    public Result forget(@RequestBody WebUserDTO webUserDTO) {
        Result result = new Result();
        try {
            WebUser webUser = queryChannelService.findOne(QWebUser.webUser.username.eq(webUserDTO.getUsername()), WebUser.class);
            if (webUser == null) {
                return result.fail().setMsg("用户不存在");
            }
            //短信验证码
            if (StringUtils.isBlank(webUserDTO.getMobileCode()) || !redisService.get("msm-" + webUserDTO.getUsername()).equals(webUserDTO.getMobileCode())) {
                return result.fail().setMsg("验证码错误");
            }
            memberApplication.modifyPassword(webUser, webUserDTO.getNewPassword());
            return result.ok();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return result.fail().setMsg("获取数据异常");
        }
    }

    /**
     * 绑定手机号
     */
    @RequestMapping(value = "/bindMobile", method = RequestMethod.PUT)
    public Result bindMobile(HttpServletRequest request, @RequestBody WebUserDTO webUserDTO) {
        Result result = new Result();
        try {
            WebUser webUser = Securitys.user(request);

            //短信验证码
            if (StringUtils.isBlank(webUserDTO.getMobileCode()) || !redisService.get("msm-" + webUserDTO.getMobile()).equals(webUserDTO.getMobileCode())) {
                return result.fail().setMsg("验证码错误");
            }
            memberApplication.bindMobile(webUser, webUserDTO.getMobile());
            return result.ok();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return result.fail().setMsg("获取数据异常");
        }
    }

    /**
     * 获取用户注册协议及商家入驻协议
     */
    @RequestMapping(value = "/protocol", method = RequestMethod.GET)
    public Result protocol() {
        Result result = new Result();
        try {
            SystemSetting setting = queryChannelService.queryOneEntity("select * from mall_system_setting limit 1", Collections.emptyMap(), SystemSetting.class);
            return result.ok().inject(ImmutableMap.of("memberRegisterProtocol", Strings.nullToEmpty(setting.getRegisterProtocol()), "merchantEnterProtocol", Strings.nullToEmpty(setting.getMerchantEnterProtocol())));
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return result.fail().setMsg(e.getMessage());
        }
    }

}
